package com.hs.service.impl;

import cn.hutool.core.util.PhoneUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hs.entity.dto.LoginDTO;
import com.hs.entity.pojo.LoginUser;
import com.hs.entity.pojo.User;
import com.hs.entity.pojo.UserRegard;
import com.hs.entity.vo.UserHomeVO;
import com.hs.entity.vo.UserInfoVO;
import com.hs.entity.vo.UserVO;
import com.hs.enums.AppHttpCodeEnum;
import com.hs.exception.SystemException;
import com.hs.mapper.UserMapper;
import com.hs.service.UserRegardService;
import com.hs.service.UserService;
import com.hs.utils.*;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.hs.constant.SystemConstant.DEFAULT_HEAD;
import static com.hs.constant.SystemConstant.DEFAULT_PASSWORD;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hs
 * @since 2023-08-05
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private RedisCache redisCache;

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private UserRegardService userRegardService;

    @Override
    public ResultResponse<UserInfoVO> loginByPhone(String phone) {
        if (StringUtils.hasText(phone)) {

            // 校验手机号格式
            if (!PhoneUtil.isPhone(phone)) {
                throw new SystemException(AppHttpCodeEnum.PHONE_FORMAT_ERROR);
            }
            User user;
            try {
                // 无该用户
                user = new User();
                user.setPhone(phone)
                        .setUserName(RandomUserInfoUtil.generateUserName(phone))
                        .setPassword(passwordEncoder.encode(DEFAULT_PASSWORD))
                        .setHead(DEFAULT_HEAD).setNickName(RandomUserInfoUtil.randomNickname())
                        .setLatestTime(new Date());
                save(user);

            } catch (DuplicateKeyException ignored) {
                user = query().eq("phone", phone).one();
                // 更新它的登录时间
                if (Objects.nonNull(user)) {
                    user.setLatestTime(new Date());
                    updateById(user);
                }
            }

            Integer userId = OptUtil.of(user, User::getId);
            // 生成 token
            String token = JwtUtil.createJWT(String.valueOf(userId));

            // 用户信息存入 redis 并设置有效期为7天
            LoginUser loginUser = new LoginUser();
            loginUser.setUser(user);
            redisCache.setCacheObject("pet:view:login:" + userId, loginUser,7*24, TimeUnit.HOURS);

            // 返回给前端的用户信息
            UserVO userVO = BeanCopyUtil.copyBean(user, UserVO.class);
            UserInfoVO userInfoVO = new UserInfoVO(userVO,token);
            return ResultResponse.ok(userInfoVO);

        }
        return ResultResponse.fail("一键登录失败！");
    }

    @Override
    public ResultResponse<UserInfoVO> login(LoginDTO loginDTO) {
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(loginDTO.getUserName(),loginDTO.getPassword());
        Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();

        // 将用户信息存入redis，并且将用户信息返回给前端
        User user = loginUser.getUser();

        Integer userId = user.getId();

        String token = JwtUtil.createJWT(userId + "");

        redisCache.setCacheObject("pet:view:login:" + userId,loginUser,7*24, TimeUnit.HOURS);

        // 返回给前端的用户信息
        UserVO userVO = BeanCopyUtil.copyBean(user, UserVO.class);
        UserInfoVO userInfoVO = new UserInfoVO(userVO,token);
        return ResultResponse.ok(userInfoVO);
    }

    @Override
    public ResultResponse<?> modifyPassword(String password) {
        User user = SecurityUserHolder.getLoginUser().getUser();
        user.setPassword(passwordEncoder.encode(password));
        updateById(user);
        return ResultResponse.ok();
    }

    @Override
    public ResultResponse<?> logout() {
        Integer userId = SecurityUserHolder.getUserId();
        redisCache.deleteObject("pet:view:login:" + userId );
        return ResultResponse.ok();
    }

    @Override
    public ResultResponse<UserHomeVO> getUserHome(Integer userId) {

        if (Objects.isNull(userId)) {
            return ResultResponse.fail(AppHttpCodeEnum.NEED_LOGIN.getCode(),AppHttpCodeEnum.NEED_LOGIN.getMsg());
        }

        User user = getById(userId);
        UserHomeVO userHomeVO = BeanCopyUtil.copyBean(user, UserHomeVO.class);
        LambdaQueryWrapper<UserRegard> regardQueryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<UserRegard> fansQueryWrapper = new LambdaQueryWrapper<>();

        regardQueryWrapper.eq(UserRegard::getUserId,userId);
        fansQueryWrapper.eq(UserRegard::getRegardUserId,userId);

        // 关注数
        int regardCount = (int) userRegardService.count(regardQueryWrapper);
        // 粉丝数
        int fansCount = (int) userRegardService.count(fansQueryWrapper);

        userHomeVO.setRegardCount(regardCount);
        userHomeVO.setFansCount(fansCount);

        return ResultResponse.ok(userHomeVO);
    }


}
